package template

import (
	"io/ioutil"
	"os"
)

type ginKind struct{}

func (g *ginKind) Gen(rootDir string) error {
	var err error
	rootDir += "/" + *projectRepo
	err = os.MkdirAll(rootDir, 0775)
	if err != nil {
		return err
	}
	common := new(commonKind)
	err = common.Gen(rootDir)
	if err != nil {
		return err
	}
	// client
	{
		clientDir := rootDir + "/client"
		err := os.MkdirAll(clientDir, 0775)
		if err != nil {
			return err
		}
		clientData := projectReplacer.Replace(templateGinClient)
		err = ioutil.WriteFile(clientDir+"/client_test.go", []byte(clientData), 0666)
		if err != nil {
			return err
		}
	}
	// go mod
	{
		modData := projectReplacer.Replace(templateGinGoMod)
		modData = versionReplacer.Replace(modData)
		err := ioutil.WriteFile(rootDir+"/go.mod", []byte(modData), 0666)
		if err != nil {
			return err
		}
	}
	// etc
	{
		etcDir := rootDir + "/etc"
		err := os.MkdirAll(etcDir, 0775)
		if err != nil {
			return err
		}
		etcAppIni := etcDir + "/app.ini.example"
		dataIni := projectReplacer.Replace(templateGinAppIniExample)
		err = ioutil.WriteFile(etcAppIni, []byte(dataIni), 0666)
		if err != nil {
			return err
		}
		etcAppDockerIni := etcDir + "/app-docker.ini.example"
		dataDockerIni := projectReplacer.Replace(templateGinAppDockerIniExample)
		err = ioutil.WriteFile(etcAppDockerIni, []byte(dataDockerIni), 0666)
		if err != nil {
			return err
		}
	}
	// other
	{
		protoDir := rootDir + "/proto"
		err := os.MkdirAll(protoDir, 0775)
		if err != nil {
			return err
		}
	}
	// router
	{
		routerDir := rootDir + "/router"
		err = os.MkdirAll(routerDir, 0775)
		if err != nil {
			return err
		}
		serverData := projectReplacer.Replace(templateGinRouterGo)
		serverData = projectProtoReplacer.Replace(serverData)
		err = ioutil.WriteFile(routerDir+"/router.go", []byte(serverData), 0666)
		if err != nil {
			return err
		}
		v1Dir := routerDir + "/v1"
		err = os.MkdirAll(v1Dir, 0775)
		if err != nil {
			return err
		}
		helloGoData := templateGinRouterV1HelloGo
		err := ioutil.WriteFile(v1Dir+"/hello.go", []byte(helloGoData), 0666)
		if err != nil {
			return err
		}
	}
	// service
	{
		serviceDir := rootDir + "/service"
		err = os.MkdirAll(serviceDir, 0775)
		if err != nil {
			return err
		}

		serviceData := projectReplacer.Replace("package service")
		err = ioutil.WriteFile(serviceDir+"/"+*projectRepo+".go", []byte(serviceData), 0666)
		if err != nil {
			return err
		}
	}
	// repository
	{
		repositoryDir := rootDir + "/repository"
		err = os.MkdirAll(repositoryDir, 0775)
		if err != nil {
			return err
		}
		err := ioutil.WriteFile(repositoryDir+"/repository.go", []byte("package repository"), 0666)
		if err != nil {
			return err
		}
	}
	// startup
	{
		startupDir := rootDir + "/startup"
		configData := projectReplacer.Replace(templateGinStartupConfig)
		err = ioutil.WriteFile(startupDir+"/config.go", []byte(configData), 0666)
		if err != nil {
			return err
		}
	}
	// vars
	{
		varsDir := rootDir + "/vars"
		err := os.MkdirAll(varsDir, 0775)
		if err != nil {
			return err
		}
		err = ioutil.WriteFile(varsDir+"/settings.go", []byte(templateGinVarsSettings), 0666)
		if err != nil {
			return err
		}
		err = ioutil.WriteFile(varsDir+"/vars.go", []byte(templateGinVarsVars), 0666)
		if err != nil {
			return err
		}
	}
	// main.go
	{
		mainData := projectReplacer.Replace(templateGinMain)
		err := ioutil.WriteFile(rootDir+"/main.go", []byte(mainData), 0666)
		if err != nil {
			return err
		}
	}
	return nil
}

func (g *ginKind) Kind() string {
	return "gin"
}

const (
	templateGinClient = `package client

import (
	"context"
	"fmt"
	"gitee.com/kelvins-io/kelvins/util/client_conn"
	"io/ioutil"
	"net/http"
	"testing"
)

var (
	host = "http://%v"
)

func TestClient(t *testing.T) {
	serviceName := "{service_name}"
	cli, err := client_conn.NewConnClient(serviceName)
	if err != nil {
		t.Error(err)
		return
	}
	endpoints, err := cli.GetEndpoints(context.TODO())
	if err != nil {
		t.Error(err)
		return
	}
	for i := 0; i < len(endpoints); i++ {
		path := fmt.Sprintf(host, endpoints[i]) + "/hello"
		t.Log("url =>", path)
		req, err := http.NewRequest(http.MethodGet, path, nil)
		if err != nil {
			t.Error(err)
			continue
		}
		resp, err := http.DefaultClient.Do(req)
		if err != nil {
			t.Error(err)
			continue
		}
		headerResp := resp.Header
		for i, v := range headerResp {
			t.Logf("%v=%v\n", i, v)
		}
		body, err := ioutil.ReadAll(resp.Body)
		if err != nil {
			t.Error(err)
			continue
		}
		err = resp.Body.Close()
		if err != nil {
			continue
		}
		t.Logf("%v response body %v\n", path, string(body))
		return
	}
}
`
	templateGinMain = `package main

import (
	"{namespace}/{service_name}/router"
	"{namespace}/{service_name}/startup"
	"gitee.com/kelvins-io/kelvins"
	"gitee.com/kelvins-io/kelvins/app"
)

const APP_NAME = "{service_name}"

func main() {
	application := &kelvins.HTTPApplication{
		Application: &kelvins.Application{
			LoadConfig: startup.LoadConfig,
			SetupVars:  startup.SetupVars,
			StopFunc:	startup.StopFunc,
			Name:       APP_NAME,
		},
		RegisterHttpGinRoute: router.RegisterHttpGinRoute,
	}
	app.RunHTTPApplication(application)
}`

	templateGinVarsVars = `package vars

var (
	EmailNoticeSetting *EmailNoticeSettingS
	EmailConfigSetting *EmailConfigSettingS
)
`
	templateGinVarsSettings = `package vars

type EmailConfigSettingS struct {
	User     string
	Password string
	Host     string
	Port     string
}

type EmailNoticeSettingS struct {
	Receivers []string
}`
	templateGinStartupConfig = `package startup

import (
	"{namespace}/{service_name}/vars"
	"gitee.com/kelvins-io/kelvins/config"
)

const (
	SectionEmailConfig = "email-config"
	SectionEmailNotice = "email-notice"
)

// LoadConfig 加载配置对象映射
func LoadConfig() error {
	// 举例说明
	vars.EmailConfigSetting = new(vars.EmailConfigSettingS)
	config.MapConfig(SectionEmailConfig, vars.EmailConfigSetting)
	
	vars.EmailNoticeSetting = new(vars.EmailNoticeSettingS)
	config.MapConfig(SectionEmailNotice, vars.EmailNoticeSetting)
	return nil
}

`
	templateGinRouterV1HelloGo = `package v1

import (
	"net/http"
	"time"
	"github.com/gin-gonic/gin"
	"gitee.com/kelvins-io/kelvins/util/gin_helper"
)

func Hello(c *gin.Context) {
	gin_helper.JsonResponse(c, http.StatusOK, gin_helper.SUCCESS, time.Now())
}

`
	templateGinRouterGo = `package router

import (
	"github.com/gin-gonic/gin"
	"{namespace}/{service_name}/router/v1"
)

func RegisterHttpGinRoute(r *gin.Engine) {
	r.GET("/hello", v1.Hello)
}

`
	templateGinAppDockerIniExample = `[kelvins-server]
Environment = "dev"

[kelvins-http-server]
Network = "tcp"
ReadTimeout = 30
WriteTimeout = 30
IdleTimeout = 30
SupportH2 = true

[kelvins-http-rate-limit]
MaxConcurrent = 0

[kelvins-logger]
RootPath = "./logs"
Level = "debug"

[kelvins-jwt]
Secret = "c9VW6ForlmzdeDkZE2i8"
TokenExpireSecond = 3600

[kelvins-mysql]
Host = "mysql5_7:3306"
UserName = "root"
Password = "micro-mall"
DBName = "{service_name}"
Charset = "utf8mb4"
PoolNum =  10
MaxIdleConns = 5
ConnMaxLifeSecond = 3600
MultiStatements = true
ParseTime = true

[kelvins-redis]
Host = "redis:6379"
Password = "oyuioyiuoyui"
DB = 12
PoolNum = 10

[kelvins-queue-amqp]
Broker = "amqp://micro-mall:szJ9aePR@127.0.0.1:5672/micro-mall"
DefaultQueue = "kelvins-template_notice"
ResultBackend = "redis://xxx@127.0.0.1:6379/8"
ResultsExpireIn = 3600
Exchange = "kelvins-template_notice"
ExchangeType = "direct"
BindingKey = "kelvins-template_notice"
PrefetchCount = 3
TaskRetryCount = 3
TaskRetryTimeout = 60

[email-config]
User = "xxx@qq.com"
Password = "xxxx"
Host = "smtp.qq.com"
Port = "465"

[email-notice]
Receivers = "610905744@qq.com"
`
	templateGinAppIniExample = `[kelvins-server]
Environment = "dev"

[kelvins-http-server]
Network = "tcp"
ReadTimeout = 30
WriteTimeout = 30
IdleTimeout = 30
SupportH2 = true

[kelvins-http-rate-limit]
MaxConcurrent = 0

[kelvins-logger]
RootPath = "./logs"
Level = "debug"

[kelvins-jwt]
Secret = "c9VW6ForlmzdeDkZE2i8"
TokenExpireSecond = 3600

[kelvins-mysql]
Host = "127.0.0.1:3306"
UserName = "root"
Password = "xxx"
DBName = "{service_name}"
Charset = "utf8mb4"
PoolNum =  10
MaxIdleConns = 5
ConnMaxLifeSecond = 3600
MultiStatements = true
ParseTime = true

[kelvins-redis]
Host = "127.0.0.1:6379"
Password = "xxx"
DB = 12
PoolNum = 10

[kelvins-queue-amqp]
Broker = "amqp://micro-mall:szJ9aePR@127.0.0.1:5672/micro-mall"
DefaultQueue = "kelvins-template_notice"
ResultBackend = "redis://xxx@127.0.0.1:6379/8"
ResultsExpireIn = 3600
Exchange = "kelvins-template_notice"
ExchangeType = "direct"
BindingKey = "kelvins-template_notice"
PrefetchCount = 3
TaskRetryCount = 3
TaskRetryTimeout = 60

[email-config]
User = "xxx@qq.com"
Password = "xxxx"
Host = "smtp.qq.com"
Port = "465"

[email-notice]
Receivers = "610905744@qq.com"
`
	templateGinGoMod = `module {namespace}/{service_name}

go 1.13

require (
	gitee.com/kelvins-io/common {version_common}
	gitee.com/kelvins-io/kelvins {version_kelvins}
	github.com/gin-gonic/gin v1.7.1
	google.golang.org/grpc v1.34.0
)`
)
